#' @author edvard
#' @time 2017.02.01
#' 
#' @description The sample interval of location data is 5 minutes.
#' The raw data contain too much redundant detail.
#' And contain many outlier.
#' Using the cluster can help us reduce the data size and remove the outlier
#' 

Sys.setenv(http_proxy="https://127.0.0.1:1080")

VisualTrajectory <- function(coordinates, z.value){
  map <- getBaiduMap(c(mean(coordinates[, 1]), mean(coordinates[, 2])), zoom = z.value)
  ggmap(map) + geom_point(data = coordinates, aes(x = lon, y = lat))
}


# Test haversine distance
# start <- getCoordinate('珠海香洲区海湾花园', formatted = T)
# end <- getCoordinate('珠海拱北口岸', formatted = T)
# distHaversine(start, end)

summary(raw.location)

# Removing some coordinates according to condition
raw.location <- raw.location %>% filter(double_longitude < 113.6, double_latitude < 22.3)

# Get the coordinates have high accuracy
coordinates <- raw.location %>% 
  filter(provider == "gps", accuracy < 72) %>%
  select(X_id, double_longitude, double_latitude, date, time_segment_no)

colnames(coordinates) <- c("X_id", "lon","lat", "date", "time_segment_no")
VisualTrajectory(coordinates[, c(2, 3)], 11)
# Construct Distance Martix
# Measurement https://en.wikipedia.org/wiki/Haversine_formula
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
# eps = 500 meter MinPts = 10. The sample frequency is every 5 minutes, 
# MinPts = 10 indicate that user stay at some place more than half an hour
db <- fpc::dbscan(coordinates.distm, eps = 200, MinPts = 360, method = "dist")
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")

# Check and get the center coorindate index
print(db)
# should set by myself
# cluster.info <- coordinates[c(10930, 1904, 1156),]
rownames(cluster.info) <- NULL

# Add new column
coordinates <- cbind(coordinates, cluster_no = db$cluster)
# Delete the outlier according to the cluster result
coordinates <- coordinates %>% filter(cluster_no != 0)






















# Time range 7:00 ~ 11:00 Morning
coordinates <- raw.location %>% 
  filter((time_segment_no >= 42 & time_segment_no <= 66)) %>%
  select(X_id, double_longitude, double_latitude)
colnames(coordinates) <- c("X_id", "lon","lat")
VisualTrajectory(coordinates[, c(2, 3)], 11)
# Construct Distance Martix
# Measurement https://en.wikipedia.org/wiki/Haversine_formula
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
# Determining the optimal eps value
# dbscan::kNNdistplot(coordinates.distm, k =  50)
# abline(h = 1000, lty = 2)

# data: data matrix, data frame or dissimilarity matrix (dist-object). Specify method = “dist” if the data should be interpreted as dissimilarity matrix or object. Otherwise Euclidean distances will be used.
# eps: Reachability maximum distance
# MinPts: Reachability minimum number of points
# scale: If TRUE, the data will be scaled
# method: Possible values are:
#   dist: Treats the data as distance matrix
# raw: Treats the data as raw data
# hybrid: Expect also raw data, but calculates partial distance matrices
db <- fpc::dbscan(coordinates.distm, eps = 500, MinPts = 10, method = "dist")  # eps = 500 meter MinPts = 10
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")

# Delete the outlier according to the cluster result



# Time range 11:00 ~ 14:00 Noon
coordinates <- raw.location %>% 
  filter((time_segment_no >= 66 & time_segment_no <= 84)) %>%
  select(X_id, double_longitude, double_latitude)
colnames(coordinates) <- c("X_id", "lon","lat")
VisualTrajectory(coordinates[, c(2, 3)], 11)
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
db <- fpc::dbscan(coordinates.distm, eps = 500, MinPts = 20, method = "dist")
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")


# Time range 14:00 ~ 18:00 Afternoon
coordinates <- raw.location %>% 
  filter((time_segment_no >= 84 & time_segment_no <= 108)) %>%
  select(X_id, double_longitude, double_latitude)
colnames(coordinates) <- c("X_id", "lon","lat")
VisualTrajectory(coordinates[, c(2, 3)], 11)
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
db <- fpc::dbscan(coordinates.distm, eps = 500, MinPts = 10, method = "dist")
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")

# Time range 18:00 ~ 24:00 Evening
coordinates <- raw.location %>% 
  filter((time_segment_no >= 108 & time_segment_no <= 144)) %>%
  select(X_id, double_longitude, double_latitude)
colnames(coordinates) <- c("X_id", "lon","lat")
VisualTrajectory(coordinates[, c(2, 3)], 11)
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
db <- fpc::dbscan(coordinates.distm, eps = 500, MinPts = 10, method = "dist")
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")

# Time range 00:00 ~ 07:00 Night
coordinates <- raw.location %>% 
  filter((time_segment_no >= 1 & time_segment_no <= 42)) %>%
  select(X_id, double_longitude, double_latitude)
colnames(coordinates) <- c("X_id", "lon","lat")
VisualTrajectory(coordinates[, c(2, 3)], 11)
coordinates.distm <- coordinates[, c(2,3)] %>% distm(fun = distHaversine)
db <- fpc::dbscan(coordinates.distm, eps = 500, MinPts = 10, method = "dist")  # eps = 100 meter MinPts = 10
fviz_cluster(db, coordinates[, c(2,3)], stand = FALSE, ellipse = T, geom = "point")


# Get detail address information from baidu map of first cluster
c(coordinates[db.info[2,2], 1], coordinates[db.info[2,2], 2]) %>% getLocation(formatted = F, pois = T)


